package com.mycompany.rest;

import java.io.Serializable;
import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.log4j.Logger;
import org.hibernate.Hibernate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;

import com.mycompany.services.dao.AbstractHibernateDAO;

public abstract class AbstractRestController<T extends Serializable, I extends Serializable> {

	protected final Logger log = Logger.getLogger(this.getClass());
	public static final String USER_ID = "id";
	protected String DATA_FIELD = "data";
	protected String ERROR_FIELD = "error";

	@Autowired
	protected View jsonView_i;

	private AbstractHibernateDAO<T, I> dao;

	@RequestMapping(value = "/todos", method = RequestMethod.GET)
	public ModelAndView getBeans() {
		try {
			List<T> beans = getDao().getList();
			log.debug("Returing: " + beans.toString());
			return new ModelAndView(jsonView_i, DATA_FIELD, beans);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("Error al intentar obtener la lista", e);
			return createErrorResponse("Error Inesperado. Comuniquese con el administrador");
		}

	}

	@RequestMapping(value = "/uno", method = RequestMethod.GET)
	public ModelAndView getById(@RequestParam(USER_ID) I id) {
		try {
			T bean = getDao().load(id);
			Hibernate.initialize(bean);
			log.debug("Returing: " + bean.toString());
			return new ModelAndView(jsonView_i, DATA_FIELD, bean);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("Error al intentar obtener el id=" + id, e);
			return createErrorResponse("Error Inesperado. Comuniquese con el administrador");
		}

	}

	@RequestMapping(value = "/cantidad", method = RequestMethod.GET)
	public ModelAndView count() {
		try {
			long count = getDao().count();
			log.debug("Returing: " + count);
			return new ModelAndView(jsonView_i, DATA_FIELD, count);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("Error al intentar obtener la cantidad", e);
			return createErrorResponse("Error Inesperado. Comuniquese con el administrador");
		}
	}

	@RequestMapping(value = "/borrar", method = RequestMethod.GET)
	public ModelAndView remove(@RequestParam(USER_ID) I id) {
		try {
			getDao().deleteById(id);
			log.debug("Returing: " + "Deleted");
			return new ModelAndView(jsonView_i, DATA_FIELD, "Deleted");
		} catch (Exception e) {
			e.printStackTrace();
			log.error("Error al intentar borrar id=" + id, e);
			return createErrorResponse("Error Inesperado. Comuniquese con el administrador");
		}
	}

	protected ModelAndView createErrorResponse(String sMessage) {
		return new ModelAndView(jsonView_i, ERROR_FIELD, sMessage);
	}

	public void setJsonView(View view) {
		jsonView_i = view;
	}

	public void setDao(AbstractHibernateDAO<T, I> dao) {
		this.dao = dao;
	}

	public AbstractHibernateDAO<T, I> getDao() {
		return dao;
	}

	@PostConstruct
	public abstract void init();

}
